﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace Mbs.Utils
{
    public class PythonEnvResult
    {
        public bool IsSuccess { get; set; }
        public string ErrorMessage { get; set; }
        public string StandardOutput { get; set; }
        public string StandardError { get; set; }

        public static PythonEnvResult Success() => new PythonEnvResult { IsSuccess = true };
        public static PythonEnvResult Fail(string error) => new PythonEnvResult { IsSuccess = false, ErrorMessage = error };

        public static PythonEnvResult ExecuteResult(string output, string error, int exitCode) => new PythonEnvResult
        {
            IsSuccess = exitCode == 0,
            StandardOutput = output,
            StandardError = error
        };
    }

    public class PythonEnvManager
    {
        private readonly string _venvPath;

        // Cross-platform detection properties
        private static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
        private static string ScriptsDirectory => IsWindows ? "Scripts" : "bin";
        private static string PythonCommand => IsWindows ? "python" : "python3";

        public PythonEnvManager()
        {
            _venvPath = Path.Combine(Environment.CurrentDirectory, "python");
        }

        // Path resolution methods
        private string GetPythonExePath() => Path.Combine(_venvPath, ScriptsDirectory, IsWindows ? "python.exe" : "python");
        private string GetPipExePath() => Path.Combine(_venvPath, ScriptsDirectory, IsWindows ? "pip.exe" : "pip");

        public PythonEnvResult IsEnvironmentReady()
        {
            try
            {
                if (!Directory.Exists(_venvPath))
                    return PythonEnvResult.Fail("Virtual environment directory not found.");

                string pythonExe = GetPythonExePath();
                if (!File.Exists(pythonExe))
                    return PythonEnvResult.Fail("Python interpreter is missing in virtual environment.");

                string pipExe = GetPipExePath();
                if (!File.Exists(pipExe))
                    return PythonEnvResult.Fail("pip is missing in virtual environment.");

                return PythonEnvResult.Success();
            }
            catch (Exception ex)
            {
                return PythonEnvResult.Fail($"Environment validation failed: {ex.Message}");
            }
        }

        public PythonEnvResult InitializePythonEnvironment(string[] parms = null)
        {
            parms ??= new[] { "numpy", "pandas", "matplotlib" };

            // 1. Check Python installation
            var checkResult = CheckPythonInstallation();
            if (!checkResult.IsSuccess)
                return PythonEnvResult.Fail("Python interpreter not found: " + checkResult.ErrorMessage);

            // 2. Create virtual environment
            if (!Directory.Exists(_venvPath))
            {
                var createResult = CreateVirtualEnvironment();
                if (!createResult.IsSuccess)
                    return createResult;
            }

            // 3. Verify pip exists
            if (!File.Exists(GetPipExePath()))
                return PythonEnvResult.Fail("pip is missing in virtual environment");

            // 4. Install dependencies
            return InstallPackages(GetPipExePath(), parms);
        }

        public PythonEnvResult ExecutePythonScript(string scriptPath, params string[] args)
        {
            try
            {
                string pythonExe = GetPythonExePath();
                if (!File.Exists(pythonExe))
                    return PythonEnvResult.Fail($"Python interpreter not found: {pythonExe}");

                if (!File.Exists(scriptPath))
                    return PythonEnvResult.Fail($"Script file not found: {scriptPath}");

                string arguments = $"\"{scriptPath}\" {string.Join(" ", args)}";
                return RunProcess(pythonExe, arguments);
            }
            catch (Exception ex)
            {
                return PythonEnvResult.Fail($"Execution exception: {ex.Message}");
            }
        }

        public PythonEnvResult ExecutePythonCode(string code)
        {
            try
            {
                string pythonExe = GetPythonExePath();
                if (!File.Exists(pythonExe))
                    return PythonEnvResult.Fail($"Python interpreter not found: {pythonExe}");

                string escapedCode = code.Replace("\"", "\\\"");
                return RunProcess(pythonExe, $"-c \"{escapedCode}\"");
            }
            catch (Exception ex)
            {
                return PythonEnvResult.Fail($"Execution exception: {ex.Message}");
            }
        }

        public PythonEnvResult ExecutePythonLongCode(string code)
        {
            string tempFile = null;
            try
            {
                tempFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
                File.WriteAllText(tempFile, code, Encoding.UTF8);

                string pythonExe = GetPythonExePath();
                if (!File.Exists(pythonExe))
                    return PythonEnvResult.Fail($"Python interpreter not found: {pythonExe}");

                return RunProcess(pythonExe, $"\"{tempFile}\"");
            }
            catch (Exception ex)
            {
                return PythonEnvResult.Fail($"Execution exception: {ex.Message}");
            }
            finally
            {
                CleanupTempFile(tempFile);
            }
        }

        private PythonEnvResult CheckPythonInstallation()
        {
            var result = RunProcess(PythonCommand, "--version");
            return result.IsSuccess
                ? PythonEnvResult.Success()
                : PythonEnvResult.Fail("Python version check failed");
        }

        private PythonEnvResult CreateVirtualEnvironment()
        {
            try
            {
                return RunProcess(PythonCommand, $"-m venv \"{_venvPath}\"");
            }
            catch (Exception ex)
            {
                return PythonEnvResult.Fail($"Virtual environment creation failed: {ex.Message}");
            }
        }

        private PythonEnvResult InstallPackages(string pipPath, IEnumerable<string> packages)
        {
            var errors = new StringBuilder();
            foreach (var package in packages)
            {
                var result = RunProcess(pipPath, $"install {package}");
                if (!result.IsSuccess)
                    errors.AppendLine($"Failed to install {package}: {result.StandardError}");
            }
            return errors.Length == 0
                ? PythonEnvResult.Success()
                : PythonEnvResult.Fail(errors.ToString());
        }

        private PythonEnvResult RunProcess(string fileName, string arguments)
        {
            try
            {
                var startInfo = new ProcessStartInfo
                {
                    FileName = fileName,
                    Arguments = arguments,
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true
                };

                // Handle Unix permissions
                if (!IsWindows && File.Exists(fileName))
                {
                    try
                    {
                        File.SetUnixFileMode(fileName,
                            UnixFileMode.UserExecute | UnixFileMode.UserRead | UnixFileMode.UserWrite);
                    }
                    catch (PlatformNotSupportedException) { /* Ignore on Windows */ }
                }

                using (var process = new Process { StartInfo = startInfo })
                {
                    process.Start();
                    string output = process.StandardOutput.ReadToEnd();
                    string error = process.StandardError.ReadToEnd();
                    process.WaitForExit();

                    return PythonEnvResult.ExecuteResult(
                        output.Trim(),
                        error.Trim(),
                        process.ExitCode
                    );
                }
            }
            catch (Exception ex)
            {
                return PythonEnvResult.Fail($"Process execution failed: {ex.Message}");
            }
        }

        private void CleanupTempFile(string path)
        {
            if (string.IsNullOrEmpty(path)) return;

            try
            {
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Temp file cleanup failed: {ex.Message}");
            }
        }

        public PythonEnvResult DeleteVirtualEnvironment()
        {
            try
            {
                if (Directory.Exists(_venvPath))
                {
                    Directory.Delete(_venvPath, true);

                    // Wait for deletion to complete
                    for (int i = 0; i < 10 && Directory.Exists(_venvPath); i++)
                    {
                        System.Threading.Thread.Sleep(100);
                    }
                }
                return PythonEnvResult.Success();
            }
            catch (Exception ex)
            {
                return PythonEnvResult.Fail($"Deletion failed: {ex.Message}");
            }
        }

        public string GetVenvPath() => _venvPath;
    }
}
